package main

import (
	"context"
	"log"
	"time"

	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/exporters/prometheus"
	"go.opentelemetry.io/otel/exporters/stdout/stdoutmetric"
	"go.opentelemetry.io/otel/sdk/metric"
	sdkmetric "go.opentelemetry.io/otel/sdk/metric"
	"go.opentelemetry.io/otel/sdk/resource"
	semconv "go.opentelemetry.io/otel/semconv/v1.32.0"
)

func main() {

	exporter, err := prometheus.New()
	if err != nil {
		panic(err)
	}
	provider := sdkmetric.NewMeterProvider(sdkmetric.WithReader(exporter))
	_ = provider.Meter("test_otel")
	// 创建资源
	res, err := newResource()
	if err != nil {
		panic(err)
	}

	// 创建 meterProvider
	// 如果自己的代码接受 meterProvider，可以直接传这个实例过去
	meterProvider, err := newMeterProvider(res)
	if err != nil {
		panic(err)
	}

	// 在程序退出前正确关闭 meterProvider，避免资源泄露
	defer func() {
		if err := meterProvider.Shutdown(context.Background()); err != nil {
			log.Println(err)
		}
	}()

	// 将其注册为全局 MeterProvider，以便通过 otel.Meter 和 otel.GetMeterProvider 获取
	// 大多数自动插桩库都默认使用全局 MeterProvider，若未设置则会退化为 no-op 实现，
	// 此时，不会产生任何数据。
	otel.SetMeterProvider(meterProvider)
	otel.SetMeterProvider(provider)
}

func newResource() (*resource.Resource, error) {
	return resource.Merge(resource.Default(),
		resource.NewWithAttributes(semconv.SchemaURL,
			semconv.ServiceName("my-service"),
			semconv.ServiceVersion("0.1.0"),
		))
}

func newMeterProvider(res *resource.Resource) (*metric.MeterProvider, error) {
	metricExporter, err := stdoutmetric.New()
	if err != nil {
		return nil, err
	}

	meterProvider := metric.NewMeterProvider(
		metric.WithResource(res),
		metric.WithReader(metric.NewPeriodicReader(metricExporter,
			// 默认间隔 1 分钟，此处为了演示设置为 3 秒
			metric.WithInterval(3*time.Second))),
	)
	return meterProvider, nil
}
